package com.hbnu.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author kittychen
 * @since 2025-10-20 17:24
 */
public class ReflectDemo {

    public static void main(String[] args) throws Exception {
        // 1、获取字节码对象
        // 1.1、通过类名获取
        Class<?> clazz = Person.class;

        // 1.2、通过对象获取
        Person p = new Person();
        Class<?> clazz2 = p.getClass();

        // 1.3、通过字符串获取
        Class<?> clazz3 = Class.forName("com.hbnu.reflect.Person");

        // 2、获取构造方法
        System.out.println("===================================2、获取构造方法====================================");
        System.out.println("2.1、获取所有的公共构造方法");
        Constructor<?>[] constructors = clazz.getConstructors();
        System.out.println("所有公共构造方法的个数：" + constructors.length + "个，分别是：");
        for (Constructor<?> constructor : constructors) {
            System.out.print("方法名：" + constructor.getName() + "，参数个数：" + constructor.getParameterCount() + "，参数类型：");
            Class<?>[] parameterTypes = constructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.print(parameterType.getName() + "\t");
            }
            System.out.println();
        }
        System.out.println("2.2、获取所有的构造方法(包括私有的)");
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        System.out.println("所有构造方法的个数：" + declaredConstructors.length + "个，分别是：");
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.print("方法名：" + declaredConstructor.getName() + "，参数个数：" + declaredConstructor.getParameterCount() + "，参数类型：");
            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.print(parameterType.getName() + "\t");
            }
            System.out.println();
        }
        System.out.println("2.3、获取指定的公共构造方法，并进行实例化");
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        Person person1 = (Person) constructor.newInstance("张三", 20);
        System.out.println("通过反射获取构造方法并创建的对象：" + person1);


        System.out.println("===================================3、获取成员属性====================================");
        Person person2 = (Person) clazz3.newInstance();  // 通过无参构造创建的对象
        System.out.println("3.1、获取所有公共成员属性");
        Field[] fields = clazz.getFields();
        System.out.println("所有公共成员属性的个数：" + fields.length + "个，分别是：");
        for (Field field : fields) {
            System.out.println("属性类型：" + field.getType().getName() + "，属性名：" + field.getName());
        }

        System.out.println("3.2、获取所有成员属性(包括私有的)");
        Field[] declaredFields = clazz.getDeclaredFields();
        System.out.println("所有成员属性的个数：" + declaredFields.length + "个，分别是：");
        for (Field field : declaredFields) {
            System.out.println("属性类型：" + field.getType().getName() + "，属性名：" + field.getName());
        }

        System.out.println("3.3、获取指定的公共成员属性");
        Field address = clazz.getField("address");
        address.set(person2, "北京");
        System.out.println("通过反射获取公共成员属性并赋值：" + person2.address);

        System.out.println("3.4、获取指定的成员属性(包括私有的)");
        Field age = clazz.getDeclaredField("age");
        age.setAccessible(true);  // 设置为可访问
        age.set(person2, 20);
        System.out.println("通过反射获取成员属性并赋值：" + person2.getAge());


        System.out.println("===================================4、获取成员方法====================================");
        System.out.println("4.1、获取所有公共成员方法(包括继承过来的方法)");
        Method[] methods = clazz.getMethods();
        System.out.println("所有公共成员方法的个数：" + methods.length + "个，分别是：");
        for (Method method : methods) {
            System.out.print("方法返回值：" + method.getReturnType().getName() + "，方法名：" +
                    method.getName() + "，参数个数：" + method.getParameterCount() + "，参数类型：");
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.print(parameterType.getName() + "，");
            }
            System.out.println();
        }
        System.out.println("4.2、获取所有的成员方法(包括私有的)");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        System.out.println("所有成员方法的个数：" + declaredMethods.length + "个，分别是：");
        for (Method declaredMethod : declaredMethods) {
            System.out.print("方法返回值：" + declaredMethod.getReturnType().getName() + "，方法名：" +
                    declaredMethod.getName() + "，参数个数：" + declaredMethod.getParameterCount() + "，参数类型：");
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.print(parameterType.getName() + "，");
            }
            System.out.println();
        }
        System.out.println("4.3、获取指定的公共成员方法");
        Method method = clazz.getMethod("sayHi");
        method.invoke(person2);
        System.out.println("4.4、获取指定的成员方法(包括私有的)");
        Method method1 = clazz.getDeclaredMethod("method", String.class);
        method1.setAccessible(true);
        String result = (String) method1.invoke(person2, "反射方式调用method()方法");
        System.out.println("反射方式调用method()方法的返回值：" + result);
    }
}
